﻿using Microsoft.EntityFrameworkCore;
using Polaris.Common;
using Polaris.Common.Extension;
using Polaris.Common.RedisHelper;
using Polaris.Domain.Interfaces.Admin;
using Polaris.Domain.Model.DbEntity;
using Polaris.Domain.Model.Dto.Permissions.Request;
using Polaris.Domain.Model.Dto.Permissions.Response;
using Polaris.Domain.Model.Dto.Sys_Dictionary_Item.Response;
using Polaris.Domain.Model.Dto.Sys_Menu.Response;
using Polaris.Domain.Model.Entity.Base;
using Polaris.Domain.Model.Entity.Exception;
using Polaris.Domain.Model.Enum;
using Polaris.Domain.Repository.Interfaces;
using Polaris.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace Polaris.Infrastructure.DomainService.Admin
{
    public class PermissionsService : IPermissions
    {
        private readonly IBaseRepository<Sys_Role> _role;
        private readonly IBaseRepository<Sys_Menu> _menu;
        private readonly IBaseRepository<Sys_MenuRole> _menuRole;
        private readonly string _baseKey = "permissions:admin";
        private readonly PolarisDbContext _dbContext;

        public PermissionsService(IBaseRepository<Sys_Role> role, IBaseRepository<Sys_Menu> menu, IBaseRepository<Sys_MenuRole> menuRole, PolarisDbContext dbContext)
        {
            _role = role;
            _menu = menu;
            _menuRole = menuRole;
            _dbContext = dbContext;
        }

        /// <summary>
        /// 创建角色
        /// </summary>
        /// <param name="create"></param>
        /// <param name="userId"></param>
        /// <exception cref="CustomException"></exception>
        public async Task CreateRole(CreateRoleInfoRequest create, Guid? userId)
        {
            try
            {
                var cacheKey1 = $"{_baseKey}:all:menu";
                var cacheKey2 = $"{_baseKey}:all";
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);

                var role = new Sys_Role()
                {
                    CreateBy = userId,
                    CreatedTime = DateTime.Now,
                    Description = create.Description,
                    Enable = create.Enable,
                    Id = Guid.NewGuid(),
                    Name = create.Name,
                };

                await _role.AddEntityAsync(role);
                await _role.CommitAsync();

                await Task.Delay(500);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteRoleAsync(string roleId, Guid? userId)
        {
            var cacheKey1 = $"{_baseKey}:all:menu";
            var cacheKey2 = $"{_baseKey}:all";
            await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
            await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);

            var role = await _role.WhereLoadEntityAsync(d => d.Id.ToString() == roleId) ?? throw new CustomException(ResultCode.NO_DATA, $"找不到id是{roleId}的数据");
            role.IsDelete = true;
            role.UpdatedBy = userId;
            role.UpdatedTime = DateTime.Now;

            _role.UpdateEntity(role);
            await _role.CommitAsync();

            await Task.Delay(500);
            await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
            await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);
        }

        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<List<RoleInfoResponse>> GetRoleList()
        {
            try
            {
                var cacheKey = $"{_baseKey}:all:menu";
                var redisData = await RedisHelper.HashGetAllAsync<RoleInfoResponse>(cacheKey);
                if (redisData != null && redisData.Count > 0)
                {
                    return redisData;
                }
                else
                {
                    Expression<Func<Sys_Role, bool>> where = e => e.IsDelete == false;

                    var roleList = await _role.QueryAll(d => !d.IsDelete).Select(d => new RoleInfoResponse()
                    {
                        Description = d.Description,
                        Id = d.Id.ToString(),
                        Name = d.Name,
                        Enable = d.Enable,
                    }).ToListAsync();

                    var roleIds = roleList.Select(d => d.Id).ToList();
                    var menus = _menuRole.WhereLoadEntityListAsNoTracking(d => roleIds.Contains(d.RoleId.ToString()))
                        .Select(d => new
                        {
                            menuId = d.MenuId.ToString(),
                            roleId = d.RoleId.ToString()
                        }).ToList();

                    roleList.ForEach(d =>
                    {
                        d.MenuIds = menus.Where(x => x.roleId == d.Id).Select(x => x.menuId).ToList();
                    });

                    await RedisHelper.HashSetAsync(cacheKey, roleList, roleList => roleList.Id);
                    return roleList;
                }
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }

        }

        /// <summary>
        /// 获取所有角色
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<List<RoleOptionsResponse>> GetRoleAllList()
        {
            try
            {
                var cacheKey = $"{_baseKey}:all";
                var redisData = await RedisHelper.HashGetAllAsync<RoleOptionsResponse>(cacheKey);
                if (redisData != null && redisData.Count > 0)
                {
                    return redisData;
                }
                else
                {
                    Expression<Func<Sys_Role, bool>> where = e => e.IsDelete == false;

                    var roleList = await _role.QueryAll(d => !d.IsDelete).Select(d => new RoleOptionsResponse()
                    {
                        Id = d.Id.ToString(),
                        Name = d.Name,
                    }).ToListAsync();

                    await RedisHelper.HashSetAsync(cacheKey, roleList, roleList => roleList.Id);
                    return roleList;
                }
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 授权菜单给角色
        /// </summary>
        /// <param name="request"></param>
        /// <param name="userId"></param>
        public async Task GrantMenuToRole(AllocationMenuRequest request, Guid? userId)
        {
            var roleMenuList = new List<Sys_MenuRole>();
            request.MenuList?.ForEach(item =>
            {
                roleMenuList.Add(new Sys_MenuRole()
                {
                    Id = Guid.NewGuid(),
                    MenuId = Guid.Parse(item),
                    RoleId = Guid.Parse(request.Id)
                });
            });
            if (roleMenuList.Count > 0)
            {
                var cacheKey1 = $"{_baseKey}:all:menu";
                var cacheKey2 = $"{_baseKey}:all";
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);

                await _menuRole.DelEntityAsync(d => d.RoleId == Guid.Parse(request.Id));
                await _menuRole.AddRangeAsync(roleMenuList);
                await _menuRole.CommitAsync();

                await Task.Delay(500);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);
            }
        }

        /// <summary>
        /// 修改角色
        /// </summary>
        /// <param name="update"></param>
        /// <param name="userId"></param>
        /// <exception cref="CustomException"></exception>
        public async Task UpdateRole(UpdateRoleInfoRequest update, Guid? userId)
        {
            try
            {
                var cacheKey1 = $"{_baseKey}:all:menu";
                var cacheKey2 = $"{_baseKey}:all";
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);

                var role = await _role.WhereLoadEntityAsync(d => d.Id.ToString() == update.Id);
                role.Name = update.Name;
                role.Description = update.Description;
                role.Enable = update.Enable;
                role.UpdatedBy = userId;
                role.UpdatedTime = DateTime.Now;

                _role.UpdateEntity(role);
                await _role.CommitAsync();

                await Task.Delay(500);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey1);
                await RedisHelper.DeleteKeysByPatternAsync(cacheKey2);
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }

        }

        /// <summary>
        /// 根据角色id获取授权菜单id
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<string>> GetMenuIdsById(string roleId)
        {
            var result = await _menuRole.QueryAll(m => m.RoleId.ToString() == roleId).Select(m => m.MenuId.ToString()).ToListAsync();
            return result;
        }

        /// <summary>
        /// 获取用户菜单列表
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<MenuNode>> GetUserMenuList(Guid userId)
        {
            var linqStr = from u in _dbContext.Sys_User
                          join rm in _dbContext.Sys_MenuRole on u.UserRole equals rm.RoleId
                          join m in _dbContext.Sys_Menu on rm.MenuId equals m.Id
                          where u.Id == userId
                          orderby m.Sort descending
                          select new MenuNode
                          {
                              Id = m.Id.ToString(),
                              ParentID = m.ParentID.ToString(),
                              Label = m.Name,
                              MenuType = m.MenuType,
                              //MenuIcon = m.MenuIcon,
                              PageUrl = m.PageUrl,
                              Router = m.Router,
                              Sort = m.Sort ?? 0
                          };
            var menuAll = await linqStr.ToListAsync();
            var result = new List<MenuNode>();
            result = BuildTreeOptimized(menuAll);
            return result;
        }

        /// <summary>
        /// 将扁平菜单列表转换成树
        /// </summary>
        /// <param name="flatList"></param>
        /// <returns></returns>
        private List<MenuNode> BuildTreeOptimized(List<MenuNode> flatList)
        {
            var nodeDict = new Dictionary<string, MenuNode>();
            var rootNodes = new List<MenuNode>();

            // 第一遍：创建所有节点并记录父子关系
            foreach (var node in flatList)
            {
                node.ParentID ??= string.Empty;

                // 使用自定义Clone方法替代with表达式
                var cloneNode = node.Clone();
                nodeDict[cloneNode.Id] = cloneNode;
            }

            // 第二遍：建立树形结构
            foreach (var node in nodeDict.Values)
            {
                if (string.IsNullOrEmpty(node.ParentID)) // 根节点
                {
                    rootNodes.Add(node);
                }
                else
                {
                    if (nodeDict.TryGetValue(node.ParentID, out var parent))
                    {
                        parent.Children.Add(node);
                    }
                    else
                    {
                        // 处理孤儿节点：提升为根节点
                        rootNodes.Add(node);
                    }
                }
            }

            // 排序（可选）
            return rootNodes
                .OrderByDescending(n => n.Sort)
                .ThenBy(n => n.Label)
                .ToList();
        }
    }


}
